﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace Xww.Text {
    public static class RegexHelper {
        static Dictionary<string, string> _helperInfo;
        public static Dictionary<string, string> HelperInfo {
            get { return _helperInfo; }
        }
        static RegexHelper() {
            _helperInfo = new Dictionary<string, string>();
            _helperInfo.Add("任意字符", ".");
            _helperInfo.Add("大写英文字母", "[A-Z]");
            _helperInfo.Add("小写英文字母", "[a-z]");
            _helperInfo.Add("中文字符", @"[\u4e00-\u9fa5]");
            _helperInfo.Add("数字", @"\d");
            _helperInfo.Add("非数字", @"\D");
            _helperInfo.Add("sep1", null);
            _helperInfo.Add("换行符 (文件中常用)", @"\n");
            _helperInfo.Add("回车符 (特殊文件中使用)", @"\r");
            //_helperInfo.Add("行尾", @"\r\n");
            _helperInfo.Add("制表符", @"\t");
            _helperInfo.Add("任意空白字符", @"\s");
            _helperInfo.Add("任意非空白字符", @"\S");
            _helperInfo.Add("sep2", null);
            _helperInfo.Add("行首(单行模式下有效)", @"^");
            _helperInfo.Add("行尾(单行模式下有效)", @"$");
            _helperInfo.Add("单词边界(零宽度，本身不计入匹配)", @"\b");
            _helperInfo.Add("sep3", null);
            _helperInfo.Add("限定前面字符出现任意次数(包括 0)", "*");
            _helperInfo.Add("限定前面字符出现任意次数(大于 0)", "+");
            _helperInfo.Add("限定前面字符出现 1 次或 0 次)", "?");
            _helperInfo.Add("限定前面字符出现 N 次(N为正整数)", "{N}");
            _helperInfo.Add("限定前面字符出现不小于 N 次(N为正整数)", "{N,}");
            _helperInfo.Add("限定前面字符出现不大于 N 次(N为正整数)", "{,N}");
            _helperInfo.Add("限定前面字符出现 N-M 次(N, M为正整数且 N<M)", "{N, M}");

        }

        public static RegexReplacer Create(string input, string output, MatchType replaceType, bool caseSensitive, bool multiline, bool toLeft) {
            RegexOptions option = RegexOptions.Multiline;
            if (!caseSensitive)
                option |= RegexOptions.IgnoreCase;
            if (multiline)
                option |= RegexOptions.Singleline;
            if (toLeft)
                option |= RegexOptions.RightToLeft;
            //else {
            //    option |= RegexOptions.Singleline;
            //}
            switch (replaceType) {
                case MatchType.Normal:
                    input = Regex.Escape(input);
                    output = Regex.Escape(output);
                    break;
                case MatchType.WildChar:
                    input = Regex.Escape(input);
                    output = output.SafeEscape();
                    input = Regex.Replace(input, @"\\\*[\*|\?]*", @"(.*?)");
                    input = Regex.Replace(input, @"\\\?[\*|\?]*", @"(.)");
                    break;
                case MatchType.Regular:
                    input = input.SafeEscape();
                    output = output.SafeEscape();
                    break;
                default:
                    break;
            }
            Regex regex = new Regex(input, option);
            return new RegexReplacer(regex, output);
        }
        ///<summary>字符串安全转换（换行符/回车符/制表符表示转义，其余皆忽略，保持原样）</summary>
        private static string SafeEscape(this string source) {
            List<char> rst = new List<char>(source.Length);
            bool lastEscape = false;
            for (int i = 0; i < source.Length; i++) {
                if (!lastEscape) {
                    if (source[i] != '\\') {
                        rst.Add(source[i]);
                    }
                    else {
                        lastEscape = true;
                    }
                }
                else {
                    char real = source[i];
                    switch (source[i]) {
                        case '\\': real = '\\'; break;
                        case 'n': real = '\n'; break;
                        case 'r': real = '\r'; break;
                        case 't': real = '\t'; break;
                        default: rst.Add(source[i - 1]); break;
                    }
                    rst.Add(real);
                    lastEscape = false;
                }
            }
            return new string(rst.ToArray());
        }
    }
    public enum MatchType {
        ///<summary>普通的查找与替换</summary>
        Normal = 0,
        ///<summary>通配符（*代表任意数量字符，?代表单一字符）</summary>
        WildChar = 1,
        ///<summary>正则表达式</summary>
        Regular
    }
}
